use std::collections::HashMap;
use axum::extract::{Path, Query};
use sea_orm::QueryFilter;
use axum::Json;
use sea_orm::{ColumnTrait, EntityTrait};
use infrastructure::{DB, db_conn};
use infrastructure::entity::{sys_user::Entity as User};
use infrastructure::entity::sys_user::Column::{Email, Username};
use infrastructure::models::page::{Page, PageParam};
use infrastructure::service::user_service::SysUserService;
use infrastructure::models::res::Res;
use infrastructure::models::sys_user::{ResultUser, UserCreateCmd, UserUpdateCmd};

pub async fn page(
    Query(page_param): Query<PageParam>,
    Query(params): Query<HashMap<String, String>>
) -> Res<Page<ResultUser>> {
    let res = SysUserService::page_user(page_param, params).await;

    match res {
        Ok(res) => Res::with_data(res),
        Err(e) => Res::with_err(&e.to_string()),
    }
}

pub async fn add(Json(create_cmd): Json<UserCreateCmd>) -> Res<String> {
    let db = DB.get_or_init(db_conn).await;

    if let Some(_) = User::find()
        .filter(Username.contains(&create_cmd.username))
        .filter(Email.contains(&create_cmd.email))
        .one(db)
        .await.unwrap() {
        return Res::with_err("用户已存在！");
    };

    match SysUserService::insert(create_cmd).await {
        Ok(res) => Res::with_data(res),
        Err(e) => Res::with_err(&e.to_string())
    }
}

pub async fn update(Json(update_cmd): Json<UserUpdateCmd>) -> Res<String> {
    let db = DB.get_or_init(db_conn).await;
    if let None = User::find_by_id(&update_cmd.id)
        .one(db)
        .await.unwrap() {
        return Res::with_err("未查询到用户");
    }

    match SysUserService::update(update_cmd).await {
        Ok(res) => Res::with_data(res),
        Err(e) => Res::with_err(&e.to_string())
    }
}

pub async fn delete(Path(id): Path<String>) -> Res<String> {

    let db = DB.get_or_init(db_conn).await;
    if let None = User::find_by_id(id.clone())
        .one(db)
        .await.unwrap() {
        return Res::with_err("未查询到用户");
    }

    match SysUserService::delete(id).await {
        Ok(res) => Res::with_data(res.rows_affected.to_string()),
        Err(e) => Res::with_err(&e.to_string()),
    }
}

pub async fn delete_all() -> Res<String> {
    match SysUserService::delete_all().await {
        Ok(res) => Res::with_data(res.rows_affected.to_string()),
        Err(e) => Res::with_err(&e.to_string()),
    }
}